/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ru.amse.podolsky.fractalarch.ui.gui;

/**
 *
 * @author Алексей
 */
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import ru.amse.podolsky.fractalarch.model.IParams.*;

public class GUI extends JFrame{

    private String filePath = "";
    private myScrollPane imagesRepresentation = null;
    private myScrollPane fractalImagesRepresentation = null;
    private mySplitPane containerForImages = null;
    private JLabel status = null;

    public GUI(){
        super("Fractal Archivator");
        InitComponents();
    }

    private void InitComponents(){
        setSize(800,600);
        setPreferredSize(new Dimension(800, 600));
        setMinimumSize(new Dimension(640,480));
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        Container c = getContentPane();

        // <editor-fold defaultstate="collapsed" desc="Set Menu Items">
        JMenuBar menu = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        JMenu actionMenu = new JMenu("Actions");
        JMenu helpMenu = new JMenu("Help");
        JMenuItem openFileMenuItem = new JMenuItem("Open");
        JMenuItem saveFileAsMenuItem = new JMenuItem("Save As");
        JMenuItem closeFileMenuItem = new JMenuItem("Close");
        JMenuItem exitMenuItem = new JMenuItem("Exit");
        JMenuItem compressMenuItem = new JMenuItem("Compress");
        JMenuItem decompressMenuItem = new JMenuItem("Decompress");
        JMenuItem nextMenuItem = new JMenuItem("Next image");
        JMenuItem previousMenuItem = new JMenuItem("Previous image");
        JMenuItem positiveZoomMenuItem = new JMenuItem("Zoom +");
        JMenuItem negativZoomMenuItem = new JMenuItem("Zoom -");
        JMenuItem aboutMenuItem = new JMenuItem("About");
        menu.add(fileMenu);
        menu.add(actionMenu);
        menu.add(helpMenu);
        fileMenu.add(openFileMenuItem);
        fileMenu.add(saveFileAsMenuItem);
        fileMenu.add(closeFileMenuItem);
        fileMenu.add(exitMenuItem);
        actionMenu.add(compressMenuItem);
        actionMenu.add(decompressMenuItem);
        actionMenu.add(nextMenuItem);
        actionMenu.add(previousMenuItem);
        actionMenu.add(positiveZoomMenuItem);
        actionMenu.add(negativZoomMenuItem);
        helpMenu.add(aboutMenuItem);
        // </editor-fold>

        // <editor-fold defaultstate="collapsed" desc="Set Menu Items Actions">
        exitMenuItem.setAction(new Actions.exitAction());
        openFileMenuItem.setAction(new Actions.openFileAction(this));
        saveFileAsMenuItem.setAction(new Actions.saveFileAsAction(this));
        closeFileMenuItem.setAction(new Actions.closeFileAction(this));
        compressMenuItem.setAction(new Actions.compressAction(this));
        decompressMenuItem.setAction(new Actions.decompressAction(this));
        nextMenuItem.setAction(new Actions.nextAction(this));
        previousMenuItem.setAction(new Actions.previousAction(this));
        positiveZoomMenuItem.setAction(new Actions.positivZoomAction());
        negativZoomMenuItem.setAction(new Actions.negativZoomAction());
        aboutMenuItem.setAction(new Actions.aboutAction());
        // </editor-fold>

        // <editor-fold defaultstate="collapsed" desc="Set Toolbar">
        JToolBar toolBar = new JToolBar();
        JButton compressButton = new JButton("Compress");
        JButton positivZoomButton = new JButton("Positive Zoom");
        JButton negativZoomButton = new JButton("Negative Zoom");
        JButton nextButton = new JButton("Next");
        JButton previousButton = new JButton("Previous");
        toolBar.add(compressButton);
        toolBar.add(positivZoomButton);
        toolBar.add(negativZoomButton);
        toolBar.add(previousButton);
        toolBar.add(nextButton);
        compressButton.setSize(new Dimension(100, 70));
        compressButton.setPreferredSize(new Dimension(100, 70));
        positivZoomButton.setSize(new Dimension(100, 70));
        positivZoomButton.setPreferredSize(new Dimension(100, 70));
        negativZoomButton.setSize(new Dimension(100, 70));
        negativZoomButton.setPreferredSize(new Dimension(100, 70));
        nextButton.setSize(new Dimension(100, 70));
        nextButton.setPreferredSize(new Dimension(100, 70));
        previousButton.setSize(new Dimension(100, 70));
        previousButton.setPreferredSize(new Dimension(100, 70));
        // </editor-fold>

        // <editor-fold defaultstate="collapsed" desc="Set Toolbar Actions">
        compressButton.setAction(new Actions.compressAction(this));
        positivZoomButton.setAction(new Actions.positivZoomAction());
        negativZoomButton.setAction(new Actions.negativZoomAction());
        previousButton.setAction(new Actions.previousAction(this));
        nextButton.setAction(new Actions.nextAction(this));
        compressButton.setText("");
        positivZoomButton.setText("");
        negativZoomButton.setText("");
        previousButton.setText("");
        nextButton.setText("");
        // </editor-fold>

        // <editor-fold defaultstate="collapsed" desc="Label">
        JLabel statusLabel = new JLabel("Program Starts");
        this.status = statusLabel;
        statusLabel.setSize(new Dimension(c.getWidth(), 20));
        statusLabel.setPreferredSize(new Dimension(c.getWidth(), 20));
        statusLabel.setMinimumSize(new Dimension(c.getWidth(), 20));
        // </editor-fold>

        // <editor-fold defaultstate="collapsed" desc="Progress Bar">
        JProgressBar progressBar = new JProgressBar();
        progressBar.setSize(new Dimension(c.getWidth(), 20));
        progressBar.setPreferredSize(new Dimension(c.getWidth(), 20));
        progressBar.setMinimumSize(new Dimension(c.getWidth(), 20));
        // </editor-fold>

        // <editor-fold defaultstate="collapsed" desc="Containers">
        Container c1 = new Container();
        c1.setSize(new Dimension(c.getWidth(), 100));
        c1.setPreferredSize(new Dimension(c.getWidth(), 100));
        c1.setMinimumSize(new Dimension(c.getWidth(), 100));
        c1.setLayout(new BorderLayout());
        c1.add(menu, BorderLayout.NORTH);
        c1.add(toolBar, BorderLayout.SOUTH);

        Container c2 = new Container();
        c2.setSize(new Dimension(c.getWidth(), 40));
        c2.setPreferredSize(new Dimension(c.getWidth(), 40));
        c2.setMinimumSize(new Dimension(c.getWidth(), 40));
        c2.setLayout(new BorderLayout());
        c2.add(progressBar, BorderLayout.NORTH);
        c2.add(statusLabel, BorderLayout.SOUTH);
        // </editor-fold>

        // <editor-fold defaultstate="collapsed" desc="SplitPane">
        mySplitPane myPane = new mySplitPane();
        //myPane.setSize(this.getWidth(), 400);
        //myPane.setPreferredSize(new Dimension(this.getWidth(), 400));
        myScrollPane imagePane = new myScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED, myScrollPane.NOTFRACTAL);
        myScrollPane fractalPane = new myScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED, myScrollPane.FRACTAL);
        myPane.add(imagePane, JSplitPane.LEFT);
        myPane.add(fractalPane, JSplitPane.RIGHT);
        this.containerForImages = myPane;
        this.imagesRepresentation = imagePane;
        this.fractalImagesRepresentation = fractalPane;
        myPane.setDividerLocation(getWidth());
        //myPane.getLeftComponent().setSize(0, this.getHeight());
        // </editor-fold>

        // <editor-fold defaultstate="collapsed" desc="Set Components Places">
        menu.setPreferredSize(new Dimension(Container.WIDTH, 30));
        menu.setSize(new Dimension(Container.WIDTH, 30));
        menu.setMaximumSize(new Dimension(Container.WIDTH, 30));
        toolBar.setPreferredSize(new Dimension(Container.WIDTH, 70));
        toolBar.setSize(new Dimension(Container.WIDTH, 70));
        toolBar.setMaximumSize(new Dimension(Container.WIDTH, 70));
        myPane.setPreferredSize(new Dimension(Container.WIDTH, 680));
        myPane.setSize(new Dimension(Container.WIDTH, 570));
        progressBar.setPreferredSize(new Dimension(Container.WIDTH, 20));
        progressBar.setSize(new Dimension(Container.WIDTH, 30));
        BoxLayout gl = new BoxLayout(c, 1);
        
        c.setLayout(gl);
        c.add(c1);
        
        c.add(myPane);
        c.add(c2);
        // </editor-fold>

        pack();

        setVisible(true);        
    }

    // <editor-fold defaultstate="collapsed" desc="myScrollPane">
    private class myScrollPane extends JScrollPane{
        private String path = "";
        private String oldpath = "";
        private BufferedImage buff = null;
        private boolean isFractal = false;
        private static final boolean FRACTAL = true;
        private static final boolean NOTFRACTAL = false;
        
        private myScrollPane(){
            super();
        }
        
        private myScrollPane(int vert, int horiz, boolean flag){
            super(vert, horiz);
            this.isFractal = flag;
        }
        
        @Override
        public void paint(Graphics g){
            g.clearRect(0, 0, this.getWidth(), this.getHeight());

            if(this.path.equals("")){
                this.buff = null;
                this.oldpath = "";
                this.repaint();
                return;
            }

            if(this.isFractal == false){
                File file = new File(path);
                try {
                    if(!this.path.equals(this.oldpath)){
                        this.buff = javax.imageio.ImageIO.read(file);
                        this.oldpath = this.path;
                    }
                } catch (IOException ex) {
                    Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
                }
                g.drawImage(this.buff, 0, 0, null);
            }else{
                if(!this.path.equals(this.oldpath)){
                    this.buff = ru.amse.podolsky.fractalarch.model.Actions.doDecompressionToViewer(this.path);
                    this.oldpath = this.path;
                }
                g.drawImage(this.buff, 0, 0, null);
            }
            
            this.repaint();
        }

        public void setPath(String pt){
            this.path = pt;
        }

        public String getPath(){
            return this.path;
        }

        public BufferedImage getImage(){
            return buff;
        }
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="mySplitpane">
    private class mySplitPane extends JSplitPane{

        private mySplitPane(){
            super();
        }

        public void paint(Graphics g){
            super.paint(g);
            setDivider();
        }
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Utils and Interface">
    public void setLabel(String s){
        this.status.setText(s);
    }

    public void setPath(String s){
        this.filePath = s;
        if(s.equals("")){
            this.imagesRepresentation.setPath(s);
            this.fractalImagesRepresentation.setPath(s);
        }
        if(extensionIsImage(s)){
            this.imagesRepresentation.setPath(s);
            this.fractalImagesRepresentation.setPath("");
        }else{
             if(extensionIsFractal(s)){
                 this.fractalImagesRepresentation.setPath(s);
                 this.imagesRepresentation.setPath("");
             }
        }
    }

    public void setPaths(String s1, String s2){
        this.filePath = s2;
        this.imagesRepresentation.setPath(s1);
        this.fractalImagesRepresentation.setPath(s2);
    }

    public void saveAs(String path){
        BufferedImage buff = null;

        //Случай, когда картинку сохраняют как картинку
        if(extensionIsImage(path) && extensionIsImage(filePath)){
            buff = this.imagesRepresentation.getImage();
            ru.amse.podolsky.fractalarch.model.Actions.doSaveAsImageToViewer(path, buff);
            filePath = path;
            this.imagesRepresentation.setPath(path);
            return;
        }

        //Случай, когда фрактальное изображение сохраняют как картинку
        if(extensionIsImage(path) && extensionIsFractal(filePath)){
            buff = this.fractalImagesRepresentation.getImage();
            ru.amse.podolsky.fractalarch.model.Actions.doSaveAsImageToViewer(path, buff);
            filePath = path;
            this.fractalImagesRepresentation.setPath("");
            this.imagesRepresentation.setPath(path);
            return;
        }

        //Случай, когда фрактал сохраняют как фрактал
        if(extensionIsFractal(path) && extensionIsFractal(filePath)){
            ru.amse.podolsky.fractalarch.model.Actions.doSaveAsFractalToViewer(filePath, path);
            filePath = path;
            this.fractalImagesRepresentation.setPath(path);
            return;
        }

        //Случай, когда картинку сохраняют как фрактал
        if(extensionIsFractal(path) && extensionIsImage(filePath)){
            buff = this.imagesRepresentation.getImage();
            ru.amse.podolsky.fractalarch.model.Actions.doCompressionToViewer(path, buff);
            filePath = path;
            this.fractalImagesRepresentation.setPath(path);
            this.imagesRepresentation.setPath("");
            return;
        }

        JOptionPane.showMessageDialog(null, "This image format are not supported", "Image format warning", JOptionPane.WARNING_MESSAGE);
    }

    public boolean saveAs(File file){
        BufferedImage buff = null;
        String path = file.getAbsolutePath();
        file.getParentFile().mkdirs();
        //Случай, когда картинку сохраняют как картинку
        if(extensionIsImage(path) && extensionIsImage(filePath)){
            buff = this.imagesRepresentation.getImage();
            ru.amse.podolsky.fractalarch.model.Actions.doSaveAsImageToViewer(path, buff);
            filePath = path;
            this.imagesRepresentation.setPath(path);
            return true;
        }

        //Случай, когда фрактальное изображение сохраняют как картинку
        if(extensionIsImage(path) && extensionIsFractal(filePath)){
            buff = this.fractalImagesRepresentation.getImage();
            ru.amse.podolsky.fractalarch.model.Actions.doSaveAsImageToViewer(path, buff);
            filePath = path;
            this.fractalImagesRepresentation.setPath("");
            this.imagesRepresentation.setPath(path);
            return true;
        }

        //Случай, когда фрактал сохраняют как фрактал
        if(extensionIsFractal(path) && extensionIsFractal(filePath)){
            ru.amse.podolsky.fractalarch.model.Actions.doSaveAsFractalToViewer(filePath, path);
            filePath = path;
            this.fractalImagesRepresentation.setPath(path);
            return true;
        }

        //Случай, когда картинку сохраняют как фрактал
        if(extensionIsFractal(path) && extensionIsImage(filePath)){
            buff = this.imagesRepresentation.getImage();
            ru.amse.podolsky.fractalarch.model.Actions.doCompressionToViewer(path, buff);
            filePath = path;
            this.fractalImagesRepresentation.setPath(path);
            this.imagesRepresentation.setPath("");
            return true;
        }

        JOptionPane.showMessageDialog(null, "This image format are not supported", "Image format warning", JOptionPane.WARNING_MESSAGE);
        return false;
    }

    public String getPath(){
        return filePath;
    }

    private static boolean extensionIsFractal(String ext){
        if(ext.length() == 0){
            return false;
        }
        int length = ext.length();
        char[] ch = ext.toCharArray();
        char[] newch = new char[length];
        int i = 1;
        while(ch[length - i] != '.'){
            newch[i] = ch[length - i];
            i++;
        }

        StringBuilder result = new StringBuilder();

        if(i == 4){
             result.append(newch[3]);
             result.append(newch[2]);
             result.append(newch[1]);
        }else{
            result.append(newch[4]);
            result.append(newch[3]);
            result.append(newch[2]);
            result.append(newch[1]);
        }

        String res = result.toString();

        return fractalTypes.include(res);
    }

    private static boolean extensionIsImage(String ext){
        if(ext.length() == 0){
            return false;
        }
        int length = ext.length();
        char[] ch = ext.toCharArray();
        char[] newch = new char[length];
        int i = 1;
        while(ch[length - i] != '.'){
            newch[i] = ch[length - i];
            i++;
        }

        StringBuilder result = new StringBuilder();

        if(i == 4){
             result.append(newch[3]);
             result.append(newch[2]);
             result.append(newch[1]);
        }else{
            result.append(newch[4]);
            result.append(newch[3]);
            result.append(newch[2]);
            result.append(newch[1]);
        }

        String res = result.toString();

        return imageTypes.include(res);
    }

    private void setDivider(){
        if(this.containerForImages == null){
            return;
        }
        if(this.imagesRepresentation.getPath().equals("")){
            this.containerForImages.setDividerLocation(0);
        }else{
            if(this.fractalImagesRepresentation.getPath().equals("")){
                this.containerForImages.setDividerLocation(this.containerForImages.getWidth());
            }else{
                this.containerForImages.setDividerLocation(this.containerForImages.getWidth()/2);
            }
        }
    }
    // </editor-fold>

}
